﻿// Inner Fire 游戏引擎库
// Assets - 资源管理器
//
// Copyright (c) 2025 by 尔西大帝. All rights reserved.
//
// 所属层级：框架层(5)
// 用于管理资源
//
// Author: 尔西大帝
// Email: 2670613871@qq.com
// Created: 2025-01-14

#pragma once

#include <EASTL/string_view.h>
#include <game/animation/animation.h>
#include <game/animation/animation_blend.h>
#include <game/map/map.h>
#include <game/resource/material.h>
#include <game/resource/model.h>
#include <game/resource/sky_box.h>
#include <game/resource/texture.h>
#include <game/resource/shader.h>
#include <ref_info.h>


namespace ifire::game {
class GameManager;

class Assets {
public:
  Assets(GameManager* game_manager, const ikit::XmlNode& root);
  Assets(const Assets& lhs) = delete;
  Assets& operator=(const Assets& lhs) = delete;
  ~Assets() = default;

  // 用于Singleton模式
  static Assets& GetInstance() { return *instance_; }

  // 通过一个Texture文件载入资源
  void LoadTextures(const eastl::string_view& filename);
  // 通过一个Material文件载入
  void LoadMaterials(const eastl::string_view& filename);
  // 通过一个Model文件载入
  void LoadModels(const eastl::string_view& filename);
  // 通过一个Animation文件载入
  void LoadAnimations(const eastl::string_view& filename);
  // 通过一个Blend文件载入
  void LoadBlends(const eastl::string_view& filename);
  // 通过一个Map文件载入
  void LoadMaps(const eastl::string_view& filename);
  // 通过一个Shader文件载入
  void LoadShaders(const eastl::string_view& filename);

  // 通过名称获得一个Materal
  Material* GetMaterial(ikit::sstr name);
  // 通过名称获得一个Texture
  Texture* GetTexture(ikit::sstr name);
  // 通过名称获得一个Model
  Model* GetModel(ikit::sstr name);
  // 通过名称获得一个Animation
  Animation* GetAnimation(ikit::sstr name, bool is_ready_required);
  // 通过名称获得一个AnimationClip，名称格式为“动画名:CLIP名”。
  // 如果只有一个名称，则获得第一个动画
  AnimationClip* GetClip(ikit::sstr name, bool is_ready_required);
  // 获得一个Mesh
  const dx::DxSubmesh& GetMesh(ikit::sstr name);
  // 获得一个Bend
  AnimationBlend* GetBlend(ikit::sstr name, bool is_ready_required);
  // 获得一个地图
  Map* GetMap(ikit::sstr name, bool is_ready_required);
  // 获得一个Shader
  Shader* GetShader(ikit::sstr name);

  // 属性访问
  eastl::vector<MaterialPtr>& Materials() { return materials_; }
  eastl::vector<TexturePtr>& Textures() { return textures_; }
  eastl::vector<ModelPtr>& Models() { return models_; }
  eastl::vector<AnimationPtr>& Animations() { return animations_; }
  eastl::vector<AnimationBlendPtr>& Blends() { return blends_; }
  eastl::vector<MapPtr>& Maps() { return maps_; }
  eastl::vector<ShaderPtr>& Shaders() { return shaders_; }

  // 进行配置
  static void Setup(ikit::rinfo<Material>& info){
    info.set(instance_->GetMaterial(info.name));
  }
  static void Setup(ikit::rinfo<Texture>& info){
    info.set(instance_->GetTexture(info.name));
  }
  static void Setup(ikit::rinfo<Model>& info){
    info.set(instance_->GetModel(info.name));
  }
  static void Setup(ikit::rinfo<Animation>& info){
    info.set(instance_->GetAnimation(info.name, false));
  }
  static void Setup(ikit::rinfo<AnimationClip>& info){
    info.set(instance_->GetClip(info.name, false));
  }
  static void Setup(ikit::rinfo<AnimationBlend>& info){
    info.set(instance_->GetBlend(info.name, false));
  }
  static void Setup(ikit::rinfo<Map>& info){
    info.set(instance_->GetMap(info.name, false));
  }
  static void Setup(ikit::rinfo<Shader>& info){
    info.set(instance_->GetShader(info.name));
  }

  // 设置默认项目，确保通过System中载入了指定的项目
  void SetupDefaultAssets();
  Material* GetDefaultMaterial() const { return default_material_; }
  Texture* GetDefaultDiffuse() const { return default_diffuse_; }
  Texture* GetEmptyNormal() const { return empty_normal_; }

  // 对装备的项目进行设置，处理由名称导致的引用
  void Setup();

private:
  // 用于Singleton模式
  static Assets* instance_;
  // 对于父级管理器的引用
  GameManager* game_manager_;
  // 项目的Material
  eastl::vector<MaterialPtr> materials_;
  // 项目的贴图
  eastl::vector<TexturePtr> textures_;
  // 项目的模型信息
  eastl::vector<ModelPtr> models_;
  // 项目的动画
  eastl::vector<AnimationPtr> animations_;
  // 项目的混合动画
  eastl::vector<AnimationBlendPtr> blends_;
  // 项目的地图
  eastl::vector<MapPtr> maps_;
  // 项目的Shadder
  eastl::vector<ShaderPtr> shaders_;

  // 默认的材质，当角色材质为空时，返回此材质
  Material* default_material_ = nullptr;
  // 默认的贴图，当角色贴图为空时，返回此贴图
  Texture* default_diffuse_ = nullptr;
  // 默认的法线贴图，当法线贴图为空时，返回此贴图
  Texture* empty_normal_ = nullptr;

  // 通过模板载入
  template <typename T>
  void LoadFile(const eastl::string_view& filename, const char* nodeName,
      eastl::vector<std::unique_ptr<T>>& container) {
    if (filename.empty()) return;

    XmlReader xml(filename.data());
    xml.Root().Foreach(nodeName, [this, &container](XmlNode& node, int index) {
      auto item = std::make_unique<T>(this, node);
      container.push_back(std::move(item));
    });
  }
};

} // namespace ifire::game